/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools compare data
 */

#ifndef HMFS_COMPARE_DATA_H
#define HMFS_COMPARE_DATA_H

#include <memory>
#include <string>
#include <sys/types.h>
#include <vector>

#include "hmfs_log.h"
#include "hmfs_fs.h"
#include "hmfs_command.h"
#include "hmfs_utils.h"

namespace OHOS {
namespace Hmfs {
struct DevInfo {
    std::string path;
    uint32_t segmentCount = 0;
    uint64_t startBlkId;
    uint64_t endBlkId;
};

struct SkipPara {
    uint32_t offset;
    uint32_t len;
};

struct FsData {
    FsData(std::string dev) : path(dev)
    {
    }

    std::string path;
    int32_t fd = -1;

    uint32_t features = 0;
    std::vector<DevInfo> deviceList;

    std::unique_ptr<char[]> blockBuf;

    std::unique_ptr<char[]> superBlockBuf;
    struct SuperBlockData *superBlock = nullptr;
    struct SuperBlockData *superBlock2 = nullptr;
    uint32_t quotaBits = 0;
    uint32_t quotaCount = 0;

    std::unique_ptr<char[]> cpBuf;
    struct CheckPointData *cp = nullptr;
    uint64_t cpOffset = 0;
    char *cpPos = nullptr;
    uint32_t curSeg[CURSEG_TYPE_MAX];

    std::unique_ptr<char[]> sitBuf;
    uint64_t sitOffset = 0;

    std::unique_ptr<char[]> natBuf;
    uint64_t natOffset = 0;
    char *natPos = nullptr;

    std::unique_ptr<char[]> ssaBuf;
    uint64_t ssaOffset = 0;

    std::unique_ptr<char[]> mainBlockBuf;
};

class CompareCmdParser : public CmdParser {
public:
    CompareCmdParser() : CmdParser(cmdPara_) {}
    ~CompareCmdParser() = default;
    void ShowCmdUsage(void) {}

private:
    CmdConfig cmdPara_;
};

#define EXTRA_ARG_COUNT_IMPL(_0, _1, _2, N, ...)    N
#define EXTRA_ARG_COUNT(...)                        EXTRA_ARG_COUNT_IMPL(0, ##__VA_ARGS__, 2,  1,  0)

#define COMPARE_NUMBER(ptr1, ptr2, member, ...)   \
    do { \
        if ((ptr1)->member != (ptr2)->member) { \
            HMFS_ERROR("%s not equal, %" PRIu64 " to %" PRIu64 "",  \
                #member, static_cast<uint64_t>((ptr1)->member), static_cast<uint64_t>((ptr2)->member));  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_ERROR("Index : %s", #__VA_ARGS__); \
            } \
            return -1; \
        } \
    } while (0)

#define COMPARE_NUMBER_NORETURN(ptr1, ptr2, member, ...)   \
    do { \
        if ((ptr1)->member != (ptr2)->member) { \
            HMFS_INFO("%s not equal, %" PRIu64 " to %" PRIu64 "",  \
                #member, static_cast<uint64_t>((ptr1)->member), static_cast<uint64_t>((ptr2)->member));  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_INFO("Index : %s", #__VA_ARGS__); \
            } \
        } \
    } while (0)

#define COMPARE_STRING(ptr1, ptr2, member, ...)   \
    do { \
        if (memcmp((ptr1)->member, (ptr2)->member, sizeof((ptr1)->member))) { \
            HMFS_ERROR("%s not equal:\nsrc = %s\ndst = %s", #member, (ptr1)->member, (ptr2)->member);  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_ERROR("Index : %s", #__VA_ARGS__); \
            } \
            return -1; \
        } \
    } while (0)

#define COMPARE_STRING_NORETURN(ptr1, ptr2, member, ...)   \
    do { \
        if (memcmp((ptr1)->member, (ptr2)->member, sizeof((ptr1)->member))) { \
            HMFS_INFO("%s not equal:\nsrc = %s\ndst = %s", #member, (ptr1)->member, (ptr2)->member);  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_INFO("Index : %s", #__VA_ARGS__); \
            } \
        } \
    } while (0)

#define COMPARE_MEMORY(ptr1, ptr2, member, ...)   \
    do { \
        if (memcmp((ptr1)->member, (ptr2)->member, sizeof((ptr1)->member))) { \
            HMFS_ERROR("%s not equal", #member);  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_ERROR("Index : %s", #__VA_ARGS__); \
            } \
            return -1; \
        } \
    } while (0)

#define COMPARE_MEMORY_NORETURN(ptr1, ptr2, member, ...)   \
    do { \
        if (memcmp((ptr1)->member, (ptr2)->member, sizeof((ptr1)->member))) { \
            HMFS_INFO("%s not equal", #member);  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_INFO("Index : %s", #__VA_ARGS__); \
            } \
        } \
    } while (0)

#define COMPARE_BUFFER(ptr1, ptr2, member, len, ...)   \
    do { \
        if (memcmp((ptr1)->member, (ptr2)->member, len)) { \
            HMFS_ERROR("%s not equal", #member);  \
            if (EXTRA_ARG_COUNT(__VA_ARGS__)) { \
                HMFS_ERROR("Index : %s", #__VA_ARGS__); \
            } \
            return -1; \
        } \
    } while (0)

} // namespace Hmfs
} // namespace OHOS
#endif
